package com.bytz.modules.cms.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions;
import com.boya.cup.flowable.service.model.response.CompleteTaskResponse;
import com.boya.cup.flowable.service.model.response.ProcessInstanceModel;
import com.bytz.common.entity.IEntity;
import com.bytz.common.entity.IFlowEntity;
import com.bytz.common.util.SecurityUtils;
import com.bytz.modules.bpm.client.model.AuditEntityBase;
import com.bytz.modules.bpm.client.model.BizFlowProperty;
import com.bytz.modules.bpm.client.model.IFlowSaveEntity;
import com.bytz.modules.bpm.client.model.StartProcessParam;
import com.bytz.modules.bpm.client.service.impl.*;
import com.bytz.modules.cms.order.constant.OrderConstants;
import com.bytz.modules.cms.order.constants.OrderFlowConstants;
import com.bytz.modules.cms.order.entity.Order;
import com.bytz.modules.cms.order.entity.OrderItem;
import com.bytz.modules.cms.order.model.AdminOrderModel;
import com.bytz.modules.cms.order.model.OrderAuditEntity;
import com.bytz.modules.cms.order.model.OrderSaveRo;
import com.bytz.modules.cms.order.service.*;
import com.bytz.modules.cms.order.util.OrderUtils;
import com.bytz.modules.cms.product.constant.ProductConstants;
import com.bytz.modules.cms.user.service.IEcAuditFlowService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @program: cms-backend
 * @description:
 * @author: KyleWang
 * @create: 2022-10-25 11:22
 **/
@Service
@Slf4j
public class OrderFlowServiceImpl extends BizFlowServiceCommonImpl<Order, OrderSaveRo, OrderAuditEntity, IOrderService, FlowProcBizPartServiceImpl> implements IOrderFlowService {

    @Autowired
    private IOrderFlowRuleService ruleService;
    @Autowired
    private IOrderItemService orderItemService;

    @Autowired
    @Lazy
    private IEcAuditFlowService ecAuditFlowService;

    @Autowired
    private IOrderEmailService emailService;

    @Autowired
    private IAdminOrderService adminOrderService;

    @Override
    public BizFlowProperty getFlowProperty() {
        return OrderFlowConstants.OrderFlowProperty.ORDER_PROPERTY;
    }


    @Override
    protected void setStartProcessBehavior() {
        this.startProcessBehavior = new DefaultStartProcessBehavior(this) {

            @Override
            public IFlowEntity beforeStartProcess(IFlowSaveEntity saveEntity, StartProcessParam startProcessParam) throws Exception {
                return super.beforeStartProcess(saveEntity, startProcessParam);
            }

            @Override
            public void afterStartProcess(IFlowEntity entity, ProcessInstanceModel pim) throws Exception {
                super.afterStartProcess(entity, pim);
                AuditEntityBase auditEntityBase = new AuditEntityBase();
                auditEntityBase.setProcInstId(pim.getProcessInstanceId());
                auditEntityBase.setBizId(pim.getBusinessKey());
                CompleteTaskResponse copy = BeanCopier.create(pim, new CompleteTaskResponse(), CopyOptions.create().ignoreNullValue()).copy();
                completeTaskBehavior.afterDoCompleteTask(copy, auditEntityBase, entity);

            }

            @Override
            public String getBusinessName(IFlowEntity entity) {
                Order order = toDbEntity(entity);
                return Stream.of(order.getContractNumber(), order.getProjectName(), "订单流程").filter(StringUtils::isNotBlank).collect(Collectors.joining(":"));
            }
        };
    }

    @Override
    protected void setFlowVariableBehavior() {

        this.flowVariableBehavior = new DefaultFlowVariableBehavior() {
            @Override
            public Map<String, Object> createFlowVariable(IFlowEntity entity, boolean startFlow) throws Exception {
                AdminOrderModel adminOrderModel = adminOrderService.getOrderModel(entity.getId(), true);
                Map<String, Boolean> bizDataMap = ruleService.runForFlow(adminOrderModel, adminOrderModel.getItem());
                HashMap<String, Object> result = new HashMap<>();
                result.put("bizData", bizDataMap);

                return result;
            }
        };
    }

    @Override
    protected void setCompleteTaskBehavior() {
        this.completeTaskBehavior = new DefaultCompleteTaskBehavior(this) {
            @Override
            public void afterDoCompleteTask(CompleteTaskResponse completeTaskResponse, AuditEntityBase auditEntity, IFlowEntity entity) throws Exception {
                super.afterDoCompleteTask(completeTaskResponse, auditEntity, entity);
                Order order = toDbEntity(entity);
                emailService.sendFlowReminderEmail(order, completeTaskResponse.getIdentityLinks(), auditEntity.getProcInstId());
            }
        };
    }

    @Override
    protected void setGetTaskAuditPageBehavior() {
        this.getTaskAuditPageBehavior = new DefaultGetTaskAuditPageBehavior(this) {
            @Override
            public IEntity buildCallbackCacheObject(IFlowEntity entity) {
                // 需要复制一个，而不是返回原来的，否则传入对象有id会被修改，在计算变量是找不到订单行
                return BeanUtil.toBean(entity, Order.class);
            }
        };


    }

    @Override
    protected void setTerminateProcessBehavior() {
        this.terminateProcessBehavior = new DefaultTerminateProcessBehavior(this) {
            @Override
            public IFlowEntity prepareTerminateProcess(AuditEntityBase auditEntity) throws Exception {
                return super.prepareTerminateProcess(auditEntity);
            }

            @Override
            public void afterTerminateProcess(AuditEntityBase auditEntity, IFlowEntity entity) throws Exception {
                Order order = toDbEntity(entity);
                boolean ecRequired = OrderUtils.ecRequired(order);
                if (ecRequired) {
                    // 手动把Order表的EcStatus改了
                    order.setEcStatus(OrderConstants.EcStatus.TERMINATED);

                    boolean terminate = ecAuditFlowService.terminate(entity.getId(), auditEntity.getTerminateProcessReason());
                    log.info("订单：{}已中止流程,", order.getContractNumber());
                    if (terminate) {
                        log.info("订单ec审批流程已终止");
                    } else {
                        log.info("订单ec审批流程未终止");
                    }
                }

                super.afterTerminateProcess(auditEntity, entity);
            }
        };
    }
}